using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Input.Touch;
using Microsoft.Xna.Framework;

namespace G4KFramework.Inputs
{
    public class GInput
    {
        public enum Direction
        {
            Up,
            Down,
            Left,
            Right
        }

        static public TouchCollection CurrentTouchLocationState;
        static public TouchCollection PreviousTouchLocationState;

        static private List<GGestureDefinition> detectedGestures = new List<GGestureDefinition>();

        Dictionary<Rectangle, bool> touchTapInputs = new Dictionary<Rectangle, bool>();
        Dictionary<Direction, float> touchSlideInputs = new Dictionary<Direction, float>();
        Dictionary<int, GGestureDefinition> gestureInputs = new Dictionary<int, GGestureDefinition>();

        public GInput()
        {
            
        }

        //------------------------------------------------------------------
        // Update Input        
        static public void BeginUpdate()
        {
            CurrentTouchLocationState = TouchPanel.GetState();
            detectedGestures.Clear();
            while (TouchPanel.IsGestureAvailable)
            {
                GestureSample gesture = TouchPanel.ReadGesture();
                detectedGestures.Add(new GGestureDefinition(gesture)); 
            }
        }
        static public void EndUpdate()
        {
            PreviousTouchLocationState = CurrentTouchLocationState;
        }

        //------------------------------------------------------------------
        // Kiem tra xem trang thai Input co dang dc press ko
        public bool IsPressed()
        {
            return IsPressed(null);
        }
        public bool IsPressed(Rectangle? currentObjectLocation)
        {
            if (IsTouchTapInputPressed())
                return true;
            if (IsGetureInputPressed(currentObjectLocation))
                return true;
            if (IsTouchSlideInputPressed())
                return true;
            return false;
        }

        //------------------------------------------------------------------------
        // Field va Properties xac dinh xem co pinch hay ko
        private bool _pinchGestureAvaible = false;
        public bool PinchGestureAvaible
        {
            get { return _pinchGestureAvaible; }
            set { _pinchGestureAvaible = value; }
        }

        //------------------------------------------------------------------------
        // Ham add mot vung can kiem tra TouchTap
        public void AddTouchTapInput(Rectangle theTouchArea, bool isReleasedPreviously)
        {
            if (touchTapInputs.ContainsKey(theTouchArea))
            {
                touchTapInputs[theTouchArea] = isReleasedPreviously;
                return;
            }
            touchTapInputs.Add(theTouchArea, isReleasedPreviously);
        }

        //------------------------------------------------------------------------
        // Ham add mot vung can kiem tra GestureType
        public void AddTouchGesture(GestureType gestureType, Rectangle touchArea)
        {
            TouchPanel.EnabledGestures = gestureType | TouchPanel.EnabledGestures;
            gestureInputs.Add(gestureInputs.Count, new GGestureDefinition(gestureType, touchArea));
            if (gestureType == GestureType.Pinch)
                _pinchGestureAvaible = true;
        }

        //------------------------------------------------------------------------
        // Ham add mot vung can kiem tra TouchSlide
        public void AddTouchSlideInput(Direction direction, float slideDistance)
        {
            if (touchSlideInputs.ContainsKey(direction))
            {
                touchSlideInputs[direction] = slideDistance;
                return;
            }
            touchSlideInputs.Add(direction, slideDistance);
        }

        //------------------------------------------------------------------------
        // Ham nay kiem tra xem cac area dang ky co dc touch hay ko
        private bool IsTouchTapInputPressed()
        {
            foreach (Rectangle touchArea in touchTapInputs.Keys)
            {
                if (touchTapInputs[touchArea]
                    && touchArea.Intersects(CurrentTouchRectangle)
                    && PreviousTouchPosition() == null)
                {
                    return true;
                }
                else if (!touchTapInputs[touchArea]
                    && touchArea.Intersects(CurrentTouchRectangle))
                {
                    return true;
                }
            }

            return false;
        }

        //------------------------------------------------------------------------
        // Ham nay kiem tra xem cac area dang ky co dc gesture hay ko
        // hoac tham so area co dc gesture hay ko
        private bool IsGetureInputPressed(Rectangle? newDetectionLocation)
        {
            _currentGestureDefinition = null;

            if (detectedGestures.Count == 0)
                return false;

            foreach (GGestureDefinition userDefinedGesture in gestureInputs.Values)
            {
                foreach (GGestureDefinition detectedGesture in detectedGestures)
                {
                    if (detectedGesture.Type == userDefinedGesture.Type)
                    {
                        Rectangle areToCheck = userDefinedGesture.CollisionArea;
                        if (newDetectionLocation != null)
                            areToCheck = (Rectangle)newDetectionLocation;

                        if (detectedGesture.CollisionArea.Intersects(areToCheck))
                        {
                            if (_currentGestureDefinition == null)
                            {
                                _currentGestureDefinition = new GGestureDefinition(detectedGesture.Gesture);
                            }
                            else
                            {
                                _currentGestureDefinition.Delta += detectedGesture.Delta;
                                _currentGestureDefinition.Delta2 += detectedGesture.Delta2;
                                _currentGestureDefinition.Position += detectedGesture.Position;
                                _currentGestureDefinition.Position2 += detectedGesture.Position2;
                            }
                        }
                    }
                }
            }

            if (_currentGestureDefinition != null)
                return true;
            
            return false;
        }

        //------------------------------------------------------------------------
        // Ham nay kiem tra xem co touch slide ko
        private bool IsTouchSlideInputPressed()
        {
            foreach (Direction slideDirection in touchSlideInputs.Keys)
            {
                Vector2? currentPosition = CurrentTouchPosition();
                Vector2? previousPosition = PreviousTouchPosition();
                if (currentPosition != null && previousPosition != null)
                {
                    switch (slideDirection)
                    {
                        case Direction.Up:
                            {
                                if (currentPosition.Value.Y + touchSlideInputs[slideDirection] < previousPosition.Value.Y)
                                    return true;
                            }
                            break;
                        case Direction.Down:
                            {
                                if (currentPosition.Value.Y - touchSlideInputs[slideDirection] > previousPosition.Value.Y)
                                    return true;
                            }
                            break;
                        case Direction.Left:
                            {
                                if (currentPosition.Value.X + touchSlideInputs[slideDirection] > previousPosition.Value.X)
                                    return true;
                            }
                            break;
                        case Direction.Right:
                            {
                                if (currentPosition.Value.X - touchSlideInputs[slideDirection] > previousPosition.Value.X)
                                    return true;
                            }
                            break;
                    }
                }
            }

            return false;
        }

        //------------------------------------------------------------------------
        // Cac ham tra ve thuoc tinh cua Gesture    
        // Chu y XNA chi phuc vu 2 touch point cung luc
        private GGestureDefinition _currentGestureDefinition;
        public Vector2 CurrentGesturePosition() // vi tri cua touch point 1
        {
            if (_currentGestureDefinition == null)
                return Vector2.Zero;

            return _currentGestureDefinition.Position;
        }
        public Vector2 CurrentGesturePosition2() // vi tri cua touch point 2
        {
            if (_currentGestureDefinition == null)
                return Vector2.Zero;

            return _currentGestureDefinition.Position2;
        }
        public Vector2 CurrentGestureDelta() // time Delta cua touch point 1
        {
            if (_currentGestureDefinition == null)
                return Vector2.Zero;
            return _currentGestureDefinition.Delta;
        }
        public Vector2 CurrentGestureDelta2() // time Delta cua touch point 2
        {
            if (_currentGestureDefinition == null)
                return Vector2.Zero;
            return _currentGestureDefinition.Delta2;
        }

        //------------------------------------------------------------------------
        // Ham tra ve Rectangle obj the hien vung bi touch
        private Rectangle CurrentTouchRectangle
        {
            get
            {
                Vector2? touchPosition = CurrentTouchPosition();
                if (touchPosition == null)
                    return Rectangle.Empty;

                return new Rectangle((int)touchPosition.Value.X - 5,
                    (int)touchPosition.Value.Y - 5, 10, 10);
            }
        }

        //------------------------------------------------------------------------
        // Ham tra ve vi tri touch hien tai
        public Vector2? CurrentTouchPosition()
        {
            foreach (TouchLocation location in CurrentTouchLocationState)
            {
                switch (location.State)
                {
                    case TouchLocationState.Pressed:
                        return location.Position;
                    case TouchLocationState.Moved:
                        return location.Position;
                }
            }
            return null;
        }

        //------------------------------------------------------------------------
        // Ham tra ve vi tri touch luc truoc
        private Vector2? PreviousTouchPosition()
        {
            foreach (TouchLocation location in PreviousTouchLocationState)
            {
                switch (location.State)
                {
                    case TouchLocationState.Pressed:
                        return location.Position;
                    case TouchLocationState.Moved:
                        return location.Position;
                }
            }
            return null;
        }
    }
}
